package com.example.demo.mqsever.core;

import com.example.demo.common.MqException;

// 使用这个类来实现交换机的转发规则
// 同时通过这个类来验证 bindingKey 是否合法
public class Router {

    public  boolean checkBindingKey(String bindingKey){
        if (bindingKey.length() == 0) {
            return true;
        }

        // 检查字符串中不能存在非法字符
        for (int i = 0; i < bindingKey.length(); i++) {
            char ch = bindingKey.charAt(i);
            if (ch >= 'A' && ch <= 'Z') {
                continue;
            }
            if (ch >= 'a' && ch <= 'z') {
                continue;
            }
            if (ch >= '0' && ch <= '9') {
                continue;
            }
            if (ch == '_' || ch == '.' || ch == '*' || ch == '#') {
                continue;
            }
            return false;
        }
        // 检查 * 或者 # 是否是独立的部分.
        String[] words = bindingKey.split("\\.");
        for (String word : words) {
            // 检查 word 长度 > 1 并且包含了 * 或者 # , 就是非法的格式了.
            if (word.length() > 1 && (word.contains("*") || word.contains("#"))) {
                return false;
            }
        }
        // 约定一下, 通配符之间的相邻关系（人为约定）
        // 只有 aaa.*.*.bbb => 合法
        for (int i = 0; i < words.length - 1; i++) {
            // 连续两个 ##
            if (words[i].equals("#") && words[i + 1].equals("#")) {
                return false;
            }
            // # 连着 *
            if (words[i].equals("#") && words[i + 1].equals("*")) {
                return false;
            }
            // * 连着 #
            if (words[i].equals("*") && words[i + 1].equals("#")) {
                return false;
            }
        }
        return true;
    }

    // 数字 + 字母 + 下划线
    // 使用.分割若干部分
    public boolean checkRoutingKey(String routingKey){
        if(routingKey.length()==0){
            return true;
        }
        for (int i = 0; i < routingKey.length(); i++) {
            char ch = routingKey.charAt(i);
           // 判断
            if (ch >= 'A' && ch <= 'Z') {
                continue;
            }
            if (ch >= 'a' && ch <= 'z') {
                continue;
            }
            if (ch >= '0' && ch <= '9') {
                continue;
            }
            if (ch == '_' || ch == '.') {
                continue;
            }
            // 该字符, 不是上述任何一种合法情况, 就直接返回 false
            return false;
        }
        return true;
    }

    // 判定该消息是否可以转发给这个绑定对应的队列
    public boolean route(ExchangeType exchangeType,Binding binding,Message message) throws MqException {
        if(exchangeType == ExchangeType.FANOUT){
            return true;
        } else if (exchangeType == ExchangeType.TOPIC){
            return routeTopic(binding,message);
        } else {
            throw new MqException("[Router] 交换机类型非法！ exchange= " + exchangeType);
        }
    }

    // 约定匹配规则
    private boolean routeTopic(Binding binding, Message message) {
        String[] bindingTokens = binding.getBindingKey().split("\\.");
        String[] routingTokens = message.getRoutingKey().split("\\.");

        // 引入两个下标
        int bindingIndex = 0;
        int routingIndex = 0;

        while (bindingIndex < bindingTokens.length && routingIndex < routingTokens.length) {
            if (bindingTokens[bindingIndex].equals("*")) {
                // * 可以匹配到任意部分
                bindingIndex++;
                routingIndex++;
                continue;
            } else if (bindingTokens[bindingIndex].equals("#")) {
                // 如果遇到 #, 需要先看看有没有下一个位置.
                bindingIndex++;
                if (bindingIndex == bindingTokens.length) {
                    //  # 匹配成功
                    return true;
                }
                //  #  拿着后面的内容, 去 routingKey 中往后找, 找到对应的位置.
                // findNextMatch 查找 返回该下标. 没找到, 就返回 -1
                routingIndex = findNextMatch(routingTokens, routingIndex, bindingTokens[bindingIndex]);
                if (routingIndex == -1) {
                    // 没找到匹配的结果. 匹配失败
                    return false;
                }
                // 找到的匹配的情况, 继续往后匹配.
                bindingIndex++;
                routingIndex++;
            } else {
                // 普通字符串, 要求两边的内容一致.
                if (!bindingTokens[bindingIndex].equals(routingTokens[routingIndex])) {
                    return false;
                }
                bindingIndex++;
                routingIndex++;
            }
        }

        // 判定是否是双方同时到达末尾
        if (bindingIndex == bindingTokens.length && routingIndex == routingTokens.length) {
            return true;
        }
        return false;
    }

    // # 查找
    private int findNextMatch(String[] routingTokens, int routingIndex, String bindingToken) {
        for (int i = routingIndex; i < routingTokens.length; i++) {
            if (routingTokens[i].equals(bindingToken)) {
                return i;
            }
        }
        return -1;
    }
}


